/**
    @project {
        "templateId": "org.helgoboss.custom",
        "version": "0.1-SNAPSHOT",
        "dependencies": [
            "org.scala-lang:scala-library:2.9.0-1",
            "org.helgoboss:scala-additions:0.1-SNAPSHOT",
            "org.helgoboss:mini-obr-runtime:0.1-SNAPSHOT",
            "org.helgoboss:osgi-additions:0.1-SNAPSHOT",
            "org.apache.felix:org.osgi.service.obr:1.0.0",
            "org.apache.felix:org.apache.felix.framework:3.0.1",
            "org.apache.felix:org.osgi.compendium:1.4.0",
            "org.apache.felix:org.apache.felix.bundlerepository:1.6.6",
            "org.helgoboss:obr-facade-ref-impl:0.3-SNAPSHOT",
            "org.helgoboss:mini-obr-runtime-bootstrapper:0.1-SNAPSHOT"
        ]
    }
*/
package org.helgoboss.mini_obr_runtime_ref_impl

import org.helgoboss.mini_obr_runtime._
import org.apache.felix.framework.util.FelixConstants
import org.osgi.framework._
import org.osgi.framework.launch._
import java.io.File
import collection.JavaConversions._
import collection.JavaConversions
import java.net.URL
import org.helgoboss.obr_facade._
import org.helgoboss.commandlet._
import org.helgoboss.osgi_additions._

class MiniObrRuntimeRefImpl (
    userHomeDir: File,
    val repositories: Iterable[URL],
    val resources: Iterable[ResourceId],
    val commandletId: Option[String],
    val commandletExecutionContext: ExecutionContext
) extends MiniObrRuntime with OsgiContext with OsgiProvider {

    whenBundleActive {
        this.providesService[MiniObrRuntime]
    }
    
    private var exitCode: Int = _

    val frameworkFactory = new org.apache.felix.framework.FrameworkFactory
    val extraPackages = List (
        "sun.misc",
        "org.helgoboss.mini_obr_runtime",
        "org.helgoboss.osgi_additions",
        "org.helgoboss.commandlet",
        "org.helgoboss.obr_facade",
        "org.osgi.service.obr",
        "org.helgoboss.scala_additions"
    )
    val felixBundleRepositoryActivator = new org.apache.felix.bundlerepository.impl.Activator
    val obrFacadeActivator = new org.helgoboss.obr_facade_ref_impl.Activator
    val bootstrapperActivator = new org.helgoboss.mini_obr_runtime_bootstrapper.Activator
    val activators = List (
        this,
        felixBundleRepositoryActivator,
        obrFacadeActivator,
        bootstrapperActivator
    )
    val frameworkConfig = Map (
        Constants.FRAMEWORK_STORAGE -> (userHomeDir.getAbsolutePath + "/.mini-obr-runtime/bundle-cache"),
        Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA -> (extraPackages.mkString(",") + scalaPackageString),
        FelixConstants.SYSTEMBUNDLE_ACTIVATORS_PROP -> JavaConversions.seqAsJavaList(activators),
        "user.home" -> userHomeDir.getAbsolutePath
    )
    val framework = frameworkFactory.newFramework(frameworkConfig)

	def start = {
        System.setProperty("java.net.useSystemProxies", "true")
        
        framework.init
        framework.start
        
        // Export dependences packages (using sysempackages_extra)
        // Start dependencies (using activator framework property)
        // 
        
        framework.waitForStop(10000)
        exitCode
	}
    
    def stop(exitCode: Int) {
        this.exitCode = exitCode
        framework.stop
    }
    
    val scalaPackageString = """scala.sys.process;uses:="scala.runtime,scala,scala.collection,scala.sys,scala.collection.immutable,scala.collection.mutable,scala.reflect,scala.xml,scala.concurrent,scala.collection.generic";version="2.9.0.1",scala.annotation.unchecked;uses:="scala.annotation,scala.reflect,scala";version="2.9.0.1",scala.reflect.generic;uses:="scala.collection.immutable,scala,scala.reflect,scala.collection.mutable,scala.runtime,scala.collection,scala.collection.generic,scala.collection.parallel,scala.math";version="2.9.0.1",scala.collection.interfaces;uses:="scala.collection,scala.reflect,scala.collection.generic,scala,scala.collection.immutable,scala.math,scala.collection.mutable";version="2.9.0.1",scala.xml.persistent;uses:="scala.xml,scala.collection.immutable,scala.collection,scala.collection.mutable,scala.runtime,scala,scala.util.logging,scala.reflect,scala.io,scala.xml.parsing,scala.xml.dtd";version="2.9.0.1",scala.actors.threadpool;uses:="scala.actors.threadpool.helpers,scala.actors.threadpool.locks";version="2.9.0.1",scala.concurrent;uses:="scala,scala.reflect,scala.runtime,scala.collection.mutable,scala.collection.immutable,scala.collection,scala.util.control,scala.collection.generic";version="2.9.0.1",scala.util.parsing.combinator.testing;uses:="scala.runtime,scala,scala.collection,scala.reflect,scala.collection.immutable,scala.util.parsing.combinator,scala.collection.mutable,scala.util.matching,scala.util.parsing.input,scala.util.parsing.combinator.lexical,scala.util.parsing.combinator.syntactical,scala.util.parsing.combinator.token";version="2.9.0.1",scala.annotation;uses:="scala.reflect,scala,scala.collection,scala.collection.immutable,scala.collection.mutable,scala.runtime";version="2.9.0.1",scala.concurrent.forkjoin;uses:="sun.misc";version="2.9.0.1",scala.reflect;uses:="scala,scala.collection.immutable,scala.runtime,scala.collection,scala.annotation,scala.collection.mutable,scala.collection.generic";version="2.9.0.1",scala.io;uses:="scala.runtime,scala,scala.collection.immutable,scala.collection,scala.math,scala.collection.mutable,scala.reflect,scala.util";version="2.9.0.1",scala.util.automata;uses:="scala.collection.immutable,scala.util.regexp,scala.runtime,scala,scala.collection,scala.collection.mutable,scala.reflect,scala.collection.generic,scala.math";version="2.9.0.1",scala.ref;uses:="scala.reflect,scala,scala.runtime";version="2.9.0.1",scala.util.parsing.syntax;uses:="scala,scala.reflect";version="2.9.0.1",scala.util.matching;uses:="scala.collection,scala.runtime,scala,scala.collection.immutable,scala.collection.generic,scala.reflect,scala.collection.mutable,scala.math";version="2.9.0.1",scala.util.parsing.combinator;uses:="scala.runtime,scala,scala.collection.immutable,scala.reflect,scala.util.matching,scala.util.parsing.input,scala.collection,scala.collection.mutable,scala.sys";version="2.9.0.1",scala.compat;uses:="scala.util,scala,scala.reflect";version="2.9.0.1",scala.runtime;uses:="scala,scala.reflect,scala.math,scala.collection.immutable,scala.util.control,scala.collection,scala.collection.mutable,scala.compat,scala.xml,scala.util,scala.collection.generic";version="2.9.0.1",scala.util.parsing.ast;uses:="scala.util.parsing.input,scala,scala.reflect,scala.runtime,scala.collection,scala.collection.immutable,scala.collection.mutable,scala.collection.parallel,scala.math,scala.collection.generic";version="2.9.0.1",scala.util.parsing.json;uses:="scala.runtime,scala,scala.collection.immutable,scala.collection,scala.util.parsing.combinator.lexical,scala.util.parsing.combinator,scala.util.parsing.input,scala.collection.generic,scala.collection.mutable,scala.reflect,scala.util.parsing.combinator.token,scala.util.parsing.combinator.syntactical";version="2.9.0.1",scala.util.logging;uses:="scala,scala.reflect";version="2.9.0.1",scala.xml.dtd;uses:="scala.collection,scala.collection.mutable,scala.runtime,scala,scala.reflect,scala.collection.immutable,scala.xml,scala.util.regexp,scala.collection.generic,scala.util.automata,scala.sys,scala.xml.parsing";version="2.9.0.1",scala.util.parsing.combinator.token;uses:="scala.runtime,scala,scala.collection,scala.collection.mutable,scala.reflect";version="2.9.0.1",scala.util.parsing.input;uses:="scala,scala.reflect,scala.runtime,scala.collection.immutable,scala.collection,scala.collection.mutable,scala.collection.generic";version="2.9.0.1",scala.testing;uses:="scala.collection.mutable,scala.runtime,scala,scala.collection.immutable,scala.collection,scala.math,scala.compat,scala.collection.generic,scala.reflect,scala.xml";version="2.9.0.1",scala.util.grammar;uses:="scala.collection,scala.runtime,scala,scala.reflect";version="2.9.0.1",scala.collection;uses:="scala.collection.immutable,scala.collection.mutable,scala,scala.collection.generic,scala.reflect,scala.math,scala.runtime,scala.collection.parallel,scala.util,scala.collection.parallel.mutable,scala.collection.script,scala.util.control";version="2.9.0.1",scala.collection.immutable;uses:="scala,scala.collection,scala.reflect,scala.runtime,scala.collection.mutable,scala.collection.generic,scala.collection.parallel,scala.math,scala.collection.parallel.immutable,scala.sys,scala.io,scala.util.matching";version="2.9.0.1",scala.text;uses:="scala.collection,scala.runtime,scala,scala.reflect,scala.collection.immutable";version="2.9.0.1",scala.actors.scheduler;uses:="scala.runtime,scala,scala.actors,scala.collection,scala.collection.mutable,scala.reflect,scala.concurrent,scala.concurrent.forkjoin,scala.sys,scala.util.control,scala.actors.threadpool,scala.actors.threadpool.locks,scala.collection.immutable,scala.util";version="2.9.0.1",scala;uses:="scala.reflect,scala.runtime,scala.util,scala.collection.mutable,scala.compat,scala.collection.generic,scala.collection,scala.collection.immutable,scala.math,scala.sys,scala.collection.parallel,scala.collection.parallel.immutable,scala.xml,scala.annotation";version="2.9.0.1",scala.actors;uses:="scala,scala.collection,scala.reflect,scala.runtime,scala.collection.immutable,scala.sys,scala.collection.mutable,scala.concurrent,scala.actors.scheduler,scala.collection.generic,scala.util.control,scala.concurrent.forkjoin";version="2.9.0.1",scala.util.continuations;uses:="scala.runtime,scala,scala.reflect,scala.annotation";version="2.9.0.1",scala.collection.parallel;uses:="scala.collection,scala.runtime,scala,scala.concurrent.forkjoin,scala.collection.generic,scala.reflect,scala.collection.mutable,scala.math,scala.collection.immutable,scala.collection.parallel.immutable,scala.collection.parallel.mutable,scala.util.control,scala.util,scala.sys";version="2.9.0.1",scala.xml.include;uses:="scala.reflect,scala";version="2.9.0.1",scala.collection.script;uses:="scala.collection,scala.runtime,scala,scala.reflect,scala.collection.mutable";version="2.9.0.1",scala.math;uses:="scala.runtime,scala,scala.collection.immutable,scala.collection,scala.collection.mutable,scala.reflect,scala.collection.generic,scala.util";version="2.9.0.1",scala.util;uses:="scala.collection.mutable,scala.reflect,scala,scala.runtime,scala.collection,scala.collection.immutable,scala.collection.generic,scala.math";version="2.9.0.1",scala.util.control;uses:="scala.reflect,scala,scala.runtime,scala.collection,scala.collection.immutable,scala.collection.generic,scala.collection.mutable,scala.sys";version="2.9.0.1",scala.actors.threadpool.helpers;uses:="scala.actors.threadpool,scala.actors.threadpool.locks";version="2.9.0.1",scala.xml.parsing;uses:="scala.collection,scala.collection.immutable,scala.collection.mutable,scala.runtime,scala,org.xml.sax,scala.reflect,scala.xml,scala.io,scala.xml.dtd,javax.xml.parsers,scala.xml.factory,org.xml.sax.helpers,scala.util.logging,scala.math,scala.sys,scala.util.automata,scala.collection.generic";version="2.9.0.1",scala.annotation.target;uses:="scala.annotation,scala.reflect,scala";version="2.9.0.1",scala.collection.parallel.immutable;uses:="scala.collection.mutable,scala.runtime,scala,scala.collection.immutable,scala.collection,scala.collection.parallel,scala.collection.generic,scala.reflect,scala.math";version="2.9.0.1",scala.sys;uses:="scala.runtime,scala,scala.reflect,scala.collection.immutable,scala.collection,scala.collection.mutable,scala.collection.parallel,scala.math,scala.collection.parallel.mutable,scala.collection.generic";version="2.9.0.1",scala.xml;uses:="scala.collection,scala.collection.mutable,scala.reflect,scala.runtime,scala,scala.xml.pull,scala.xml.dtd,scala.collection.immutable,scala.collection.generic,scala.collection.parallel,scala.math,scala.collection.parallel.immutable,scala.xml.parsing,org.xml.sax,scala.util,scala.xml.factory,javax.xml.parsers,scala.util.control";version="2.9.0.1",scala.parallel;uses:="scala.runtime,scala,scala.reflect";version="2.9.0.1",scala.actors.remote;uses:="scala.runtime,scala,scala.collection,scala.reflect,scala.actors,scala.collection.mutable,scala.collection.generic,scala.collection.immutable,scala.util";version="2.9.0.1",scala.collection.mutable;uses:="scala.collection,scala.reflect,scala,scala.collection.generic,scala.runtime,scala.collection.immutable,scala.collection.parallel,scala.math,scala.collection.script,scala.collection.parallel.mutable,scala.sys,scala.util.matching";version="2.9.0.1",scala.actors.threadpool.locks;uses:="scala.actors.threadpool,scala.actors.threadpool.helpers";version="2.9.0.1",scala.util.regexp;uses:="scala.collection,scala.runtime,scala,scala.reflect";version="2.9.0.1",scala.collection.parallel.mutable;uses:="scala.collection.mutable,scala.reflect,scala,scala.runtime,scala.collection.generic,scala.collection,scala.collection.parallel,scala.collection.immutable,scala.math,scala.sys,scala.collection.parallel.immutable";version="2.9.0.1",scala.xml.include.sax;uses:="scala.collection.immutable,scala.collection,scala.util.matching,scala.runtime,scala,scala.reflect,org.xml.sax.helpers,org.xml.sax,scala.xml,scala.collection.mutable,scala.util.control,scala.xml.include,org.xml.sax.ext";version="2.9.0.1",scala.xml.factory;uses:="scala.xml,scala.runtime,scala,scala.collection.immutable,scala.collection,scala.collection.mutable,scala.reflect,scala.xml.parsing,scala.util.logging,scala.collection.generic,javax.xml.parsers,org.xml.sax.helpers,org.xml.sax";version="2.9.0.1",scala.xml.transform;uses:="scala.xml,scala.collection,scala.runtime,scala,scala.collection.mutable,scala.reflect,scala.collection.generic";version="2.9.0.1",scala.util.parsing.combinator.lexical;uses:="scala.runtime,scala,scala.collection,scala.util.parsing.combinator,scala.reflect,scala.util.parsing.combinator.token,scala.util.parsing.input,scala.collection.mutable,scala.collection.immutable,scala.math,scala.util,scala.collection.generic";version="2.9.0.1",scala.util.parsing.combinator.syntactical;uses:="scala.util.parsing.combinator.lexical,scala.collection.mutable,scala.util.parsing.combinator,scala.reflect,scala.util.parsing.combinator.token,scala.runtime,scala";version="2.9.0.1",scala.xml.pull;uses:="scala.runtime,scala,scala.collection,scala.reflect,scala.xml,scala.xml.parsing,scala.collection.immutable,scala.collection.mutable,scala.xml.dtd,scala.io,scala.math";version="2.9.0.1",scala.collection.generic;uses:="scala.collection,scala.runtime,scala,scala.reflect,scala.collection.immutable,scala.collection.mutable,scala.collection.parallel,scala.math";version="2.9.0.1""""
    
}